package cn.wygandwdn.core.config;


import cn.wygandwdn.common.config.RegistryConfig;
import cn.wygandwdn.common.enumeration.SerializerType;
import cn.wygandwdn.common.factory.SingletonFactory;
import cn.wygandwdn.common.utils.IdWorker;
import cn.wygandwdn.core.cache.RequestCache;
import cn.wygandwdn.core.cache.caffeine.CaffeineCache;
import cn.wygandwdn.core.loadbalancer.LoadBalancer;
import cn.wygandwdn.core.loadbalancer.RandomLoadBalancer;
import cn.wygandwdn.core.loadbalancer.RoundRobinLoadBalancer;
import cn.wygandwdn.core.registry.ServiceDiscovery;
import cn.wygandwdn.core.registry.ServiceRegistry;
import cn.wygandwdn.core.registry.nacos.NacosDiscovery;
import cn.wygandwdn.core.registry.nacos.NacosRegistry;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.google.common.collect.Maps;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

import static cn.wygandwdn.common.constant.RpcConstants.*;

/**
 * @description: 读取properties配置文件的工具类
 * @author WYG
 */
public abstract class Config {
    static Properties properties;
    static Map<String, Integer> map;
    static {
        map = Maps.newHashMap();
        map.put(SerializerType.Proto.getType(), SerializerType.Proto.getCode());
        map.put(SerializerType.Gson.getType(), SerializerType.Gson.getCode());
        map.put(SerializerType.Kryo.getType(), SerializerType.Kryo.getCode());

        try (InputStream in = Config.class.getResourceAsStream("/wt-rpc.properties")) {
            properties = new Properties();
            properties.load(in);
        } catch (IOException e) {
            throw new ExceptionInInitializerError(e);
        }
    }



    /**
     * 获取服务器监听的端口号,默认为8080
     * @return  RPC-Netty服务器监听的端口
     */
    public static int getServerPort() {
        String value = properties.getProperty("rpc.server.port");
        if (value == null) {
            return 8080;
        } else {
            return Integer.parseInt(value);
        }
    }

    /**
     * 获取网络通信过程中使用的序列化器类型,默认为protostuff
     * @return  Rpc网络通信消息序列化器类型
     */
    public static Integer getSerializeType() {
        String value = properties.getProperty("serialize.type");
        if (value == null) {
            return map.get(SerializerType.Proto.getType());
        } else {
            Integer res = map.get(value);
            if (res == null) {
                return map.get(SerializerType.Proto.getType());
            } else {
                return res;
            }
        }
    }

    /**
     * 获取雪花算法的实现类,根据雪花算法生成分布式唯一id,可以选用其他实现分布式id的工具类
     * @return  雪花算法实现类
     */
    public static IdWorker getIdWorker() {
        String workerId = properties.getProperty("snow.flake.workId");
        String datacenterId = properties.getProperty("snow.flake.datacenter");
        String sequence = properties.getProperty("snow.flake.sequence");
        IdWorker idWorker = IdWorker.getInstance(Integer.parseInt(workerId), Integer.parseInt(datacenterId),
                Integer.parseInt(sequence));
        return idWorker;
    }

    /**
     * 获取服务发现实现类,这里只做了nacos的服务发现,可根据需要实现ServiceDiscovery接口,实现其他服务发现
     * @return  服务发现
     */
    public static ServiceDiscovery getDiscovery() {
        String registry = properties.getProperty("registry");
        String balancer = properties.getProperty("load.balancer");
        LoadBalancer loadBalancer = null;
        if (RANDOM.equals(balancer)) {
            loadBalancer = SingletonFactory.getInstance(RandomLoadBalancer.class);
        } else if (ROUND.equals(balancer)) {
            loadBalancer = SingletonFactory.getInstance(RoundRobinLoadBalancer.class);
        }
        if (NACOS.equals(registry)) {
            return NacosDiscovery.getInstance(loadBalancer);
        } else {
            return NacosDiscovery.getInstance(loadBalancer);
        }
    }

    /**
     * 获取实际的服务注册中心,这里只实现了Nacos注册中心,可根据实际需要实现ServiceRegistry接口,实现其他注册中心
     * @return  服务注册中心
     */
    public static ServiceRegistry getRegistry() {
        String registry = properties.getProperty("registry");
        if (NACOS.equals(registry)) {
            return SingletonFactory.getInstance(NacosRegistry.class);
        } else {
            return SingletonFactory.getInstance(NacosRegistry.class);
        }
    }

    /**
     * 获取服务注册发现中心的配置信息,可以只配置地址信息,不配置用户名和密码
     * @return
     */
    public static RegistryConfig getConfig() {
        String address = properties.getProperty("registry.address");
        String username = properties.getProperty("registry.username");
        String password = properties.getProperty("registry.password");
        if (username != null && password != null) {
            return new RegistryConfig(address, username, password);
        } else {
            return new RegistryConfig(address);
        }
    }

    /**
     * 获取超时时间,默认为1000ms
     * @return
     */
    public static int getTimeout() {
        String timeout = properties.getProperty("rpc.timeout");
        if (timeout == null) {
            return 1000;
        } else {
            return Integer.parseInt(timeout);
        }
    }

    /**
     * 获取超时重试次数,默认超时重试次数为2
     * @return
     */
    public static int getRetry() {
        String retries = properties.getProperty("rpc.retries");
        if (retries == null) {
            return 2;
        } else {
            return Integer.parseInt(retries);
        }
    }

    /**
     * 获取本地缓存实现类,单例;默认为Caffeine;可以提供其他本地缓存的实现
     * @return
     */
    public static RequestCache getCache() {
        String cacheType = properties.getProperty("request.cache");
        return CaffeineCache.getInstance();
    }
}